using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Xml;
using System.Xml.Serialization;
using log4net;
using NHibernate;
using TanashCMS.Business.Utilities;
using TanashCMS.Business.Utility;

namespace TanashCMS.Business
{
    [DataObject(true),Serializable()]
    public abstract class CMSDataObject : System.Object
    {
        private static readonly ILog actionLog = LogManager.GetLogger(typeof(CMSDataObject));
        protected int mID;
        protected string mGUID;
        protected string mTitle;
        protected CMSObjectState mState;
        protected DateTime? mLastUpdated;
        protected DateTime mDateCreated = DateTime.Now;
        protected CMSObjectType mObjectType;
        protected string mHtmlContent;
        protected string mMasterPage;
        protected string mItemKey;

        public static t getByGUID<t>(string GUID) where t:CMSDataObject
        {
            ISession session = Configuration.GetCurrentSession();
            ICriteria crit = session.CreateCriteria(typeof(t));
            crit.Add(new NHibernate.Expression.EqExpression("GUID", GUID));

            return (t)crit.UniqueResult();
        }

        public static t getByGUID<t>(int id) where t : CMSDataObject
        {
            ISession session = Configuration.GetCurrentSession();
            ICriteria crit = session.CreateCriteria(typeof(t));
            crit.Add(new NHibernate.Expression.EqExpression("ID", id));

            return (t)crit.UniqueResult();
        }

        public virtual CMSObjectType ObjectType { get { return mObjectType; } set { mObjectType = value; } }

        public virtual int ID
        {
            get { return mID; }
            set { mID = value; }
        }

        public static string GetKey(string value)
        {
            return Sanitiser.Alpha(value); 
        }

        public virtual string ItemKey
        {
            get {
                return mItemKey; 
            }
            set { mItemKey = value; }
        }

        public virtual DateTime? LastUpdated { get { return mLastUpdated; } set { mLastUpdated = value; } }
        public virtual DateTime DateCreated { get { return mDateCreated; } set { mDateCreated = value; } }

        public virtual string GUID
        {
            get { return mGUID; }
            set { mGUID = value; }
        }

        public virtual string Title
        {
            get { return mTitle;  }
            set { mTitle = value; mItemKey = GetKey(value); }
        }

        public virtual string HTMLContent { get { return mHtmlContent; } set { mHtmlContent = value; } }
        public virtual string MasterPage { get { return mMasterPage; } set { mMasterPage = value; } }

        public virtual CMSObjectState State
        {
            get { return mState; }
            set { mState = value; }
        }

        public override string ToString()
        {
            return mTitle;
        }

        public static CMSDataObject Get(CMSObjectType cmstype, int id)
        {
            if (cmstype == CMSObjectType.Product)
                return getByGUID<Product>(id);
            else if (cmstype == CMSObjectType.Category)
                return getByGUID<Category>(id);
            else if (cmstype == CMSObjectType.WebPage)
                return getByGUID<WebPage>(id);
            else if (cmstype == CMSObjectType.Navigation)
                return getByGUID<Navigation>(id);

            return null;
        }
        public string GetUrl()
        {
            CMSDataObject cmsObject = this;
            if (cmsObject.ObjectType == CMSObjectType.Product)
                return GetUrlForProduct(cmsObject as Product);
            else if (cmsObject.ObjectType == CMSObjectType.Category)
                return GetUrlForCategory(cmsObject as Category);
            else if (cmsObject.ObjectType == CMSObjectType.WebPage)
                return GetUrlForPage(cmsObject as WebPage);

            return "";
        }
        private string GetUrlForProduct(Product p)
        {
            StringBuilder sb = new StringBuilder();
            sb.Insert(0,"/" + p.ItemKey + ".t");
            Category c = Category.Get(p.CategoryID);
            sb.Insert(0,GetUrlForCategory(c, true));
            sb.Insert(0, "/website/inventory");
            return sb.ToString();
        }
        private string GetUrlForCategory(Category c, bool AppendHtmlExtension)
        {
            StringBuilder sb = new StringBuilder();
            sb.Insert(0, "/" + c.ItemKey);
            if (AppendHtmlExtension)
                sb.Append(".t");

            while (c.ParentID != 0)
            {
                c = Category.Get(c.ParentID);
                sb.Insert(0, "/" + c.ItemKey);
            }

            sb.Insert(0, "/website/inventory");
            return sb.ToString();
        }
        private string GetUrlForCategory(Category c)
        {
            return GetUrlForCategory(c, true);
            
        }
        private string GetUrlForPage(WebPage p)
        {
            StringBuilder sb = new StringBuilder();
            sb.Insert(0, p.ItemKey + ".t");
            while (p.ParentPageID != 0)
            {
                p = WebPage.Select(p.ParentPageID);
                sb.Insert(0, "/" + p.ItemKey);
            }
            return sb.ToString();
        }

        public virtual void Save()
        {
            Configuration.GetCurrentSession().Save(this);
            Configuration.GetCurrentSession().Flush();
        }

        public static void LogAction(CMSDataObject o, string action, string username)
        {
            StringBuilder sb = new StringBuilder();
            XmlWriter w = XmlWriter.Create(sb);
            new XmlSerializer(o.GetType()).Serialize(w, o);
            w.Flush();
            w.Close();
            actionLog.Debug(string.Format("{0} {1} {2} {3}\n{4}", username, action, o, o.ID, sb.ToString()));
        }
    }
}
